package org.leo.dm.util.beanvalidate;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.leo.dm.util.exception.DmException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * Created on 2016年2月17日
 * <p>
 * Description 规则验证核心实现类
 * <p>
 * Copyright neusoft (c) 2015 .
 * 
 * @author xiao_h
 *
 */
public class RuleService {

	static Logger log = LoggerFactory.getLogger(RuleService.class);

	// private static String LINE_SEPARATOR = System.getProperty("line.separator");
	// private static String VERTICAL_LINE_SEPARATOR = "|";
	private static final String SEMICOLON_SEPARATOR = ";";

	/**
	 * 返回值为String类型
	 * 
	 * @param object
	 *            被验证的实例化对象
	 * @param xmlValidate
	 *            String格式的验证Xml
	 * @return
	 * @throws Exception
	 */
	public static String validStr(Object object, String xmlValidate) throws Exception {
		String outStr = "";
		try {
			log.info(object.getClass().getName() + "对象属性值验证开始解析");
			Map<String, List<String>> map = validCollec(object, xmlValidate);
			for (Map.Entry<String, List<String>> entry : map.entrySet()) {
				for (String ls : entry.getValue()) {
					outStr = outStr + entry.getKey() + ":" + ls + SEMICOLON_SEPARATOR;
				}
			}
			log.info(object.getClass().getName() + "对象属性值验证结束解析");
		} catch (Exception e) {
			throw new DmException("参数校验过程异常", e);
		}
		return outStr;
	}

	/**
	 * 解析入口 返回值为集合类型
	 * 
	 * @param object
	 *            被验证的实例化对象
	 * @param xmlValidate
	 *            String格式的验证Xml
	 * @return
	 * @throws Exception
	 */
	public static Map<String, List<String>> validCollec(Object object, String xmlValidate) throws Exception {
		Map<String, List<String>> map = new LinkedHashMap<String, List<String>>();
		List<String> listTemp = null;
		if (object == null) {
			throw new DmException("未获取到被验证的Bean实例");
		}
		if (xmlValidate == null) {
			throw new DmException("未获取到Bean的验证规则XML");
		}
		// 获取校验规则
		Document docValidate = DocumentHelper.parseText(xmlValidate);
		Element rootValidate = docValidate.getRootElement();
		// 获取object的类型
		Class<? extends Object> clazz = object.getClass();
		// 获取该类型声明的成员
		Field[] fields = clazz.getDeclaredFields();
		// 遍历属性
		for (Field field : fields) {
			// 对于private私有化的成员变量，通过setAccessible来修改器访问权限 提高反射获取属性速度
			field.setAccessible(true);
			listTemp = validate(field, object, rootValidate);
			if (listTemp.size() > 0) {
				map.put(field.getName(), listTemp);
			}
			// 重新设置会私有权限
			field.setAccessible(false);
		}
		return map;
	}

	private static List<String> validate(Field field, Object object, Element rootValidate) throws Exception {
		List<String> listTemp = new ArrayList<String>();
		Attribute descriptionAttr = null;
		Attribute nullableAttr = null;
		Attribute minLengthAttr = null;
		Attribute maxLengthAttr = null;
		Attribute regexTypeAttr = null;
		Attribute regexExpressionAttr = null;
		Attribute inAttr = null;
		Attribute startAttr = null;
		Attribute endAttr = null;

		String description = null;

		// 获取对象的成员的元素信息
		Element mEle = rootValidate.element(field.getName());
		if (mEle == null) {
			return listTemp;
		}
		Object value = field.get(object);
		descriptionAttr = mEle.attribute("description");
		if (descriptionAttr == null || descriptionAttr.getText().equals("")) {
			description = field.getName();
		} else {
			description = descriptionAttr.getText();
		}

		nullableAttr = mEle.attribute("nullable");
		if (nullableAttr != null && !Boolean.valueOf(nullableAttr.getText())) {
			if (value == null || StringUtils.isBlank(value.toString())) {
				listTemp.add(description + "不能为空");
			}
		}

		if (value != null && StringUtils.isNotBlank(value.toString())) {// 值不为空做以下判断
			maxLengthAttr = mEle.attribute("maxLength");
			if (maxLengthAttr != null && (value.toString().getBytes("UTF-8").length > Integer.valueOf(maxLengthAttr.getText()))) {
				listTemp.add(description + "长度不能超过" + maxLengthAttr.getText() + " 而当前值长度（UTF-8字节长度）为" + value.toString().getBytes("UTF-8").length);
			}

			minLengthAttr = mEle.attribute("minLength");
			if (minLengthAttr != null && (value.toString().getBytes("UTF-8").length < Integer.valueOf(minLengthAttr.getText()))) {
				listTemp.add(description + "长度不能小于" + minLengthAttr.getText() + " 而当前值长度（UTF-8字节长度）为" + value.toString().getBytes("UTF-8").length);
			}

			regexTypeAttr = mEle.attribute("regexType");
			if (regexTypeAttr != null && Enum.valueOf(RegexType.class, regexTypeAttr.getText()) != RegexType.NONE) {
				switch (Enum.valueOf(RegexType.class, regexTypeAttr.getText())) {
				case NONE:
					break;
				case SPECIALCHAR:
					if (RegexUtils.hasSpecialChar(value.toString())) {
						listTemp.add(description + "不能含有特殊字符");
					}
					break;
				case CHINESE:
					if (RegexUtils.isChinese2(value.toString())) {
						listTemp.add(description + "不能含有中文字符");
					}
					break;
				case EMAIL:
					if (!RegexUtils.isEmail(value.toString())) {
						listTemp.add(description + "格式不正确");
					}
					break;
				case IP:
					if (!RegexUtils.isIp(value.toString())) {
						listTemp.add(description + "格式不正确");
					}
					break;
				case NUMBER:
					if (!RegexUtils.isNumber(value.toString())) {
						listTemp.add(description + "存在非数字字符");
					}
					break;
				case PHONENUMBER:
					if (!RegexUtils.isPhoneNumber(value.toString())) {
						listTemp.add(description + "格式不正确");
					}
					break;
				case POSITIVE_INTEGER:
					if (!RegexUtils.isPositiveInteger(value.toString())) {
						listTemp.add(description + "不是正整数");
					}
					break;
				default:
					break;
				}
			}

			regexExpressionAttr = mEle.attribute("regexExpression");
			if (regexExpressionAttr != null && !regexExpressionAttr.getText().equals("")) {
				if (!value.toString().matches(regexExpressionAttr.getText())) {
					listTemp.add(description + "格式不正确");
				}
			}

			inAttr = mEle.attribute("in");
			if (inAttr != null && !inAttr.getText().equals("")) {
				
				if (!Arrays.asList(inAttr.getText().split(",")).contains(value.toString())) {
					listTemp.add(description + "值不正确 不在（" + inAttr.getText() + "）的值域之中");
				}
			}

			startAttr = mEle.attribute("start");
			if (startAttr != null && !startAttr.getText().equals("")) {
				if (!value.toString().startsWith(startAttr.getText())) {
					listTemp.add(description + "值未以" + startAttr.getText() + "开头");
				}
			}

			endAttr = mEle.attribute("end");
			if (endAttr != null && !endAttr.getText().equals("")) {
				if (!value.toString().endsWith(endAttr.getText())) {
					listTemp.add(description + "值未以" + endAttr.getText() + "结尾");
				}
			}
		}

		return listTemp;
	}

}
